#include <iostream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <vector>
#include "XmlMap.h"
#include "tinyxml.h"
#include "tinystr.h"
#include "Eigen/Geometry"

using namespace std;
using namespace Eigen;

LabyrinthMap::LabyrinthMap(int h, int w)
{
	const char* mapXml = "<Map></Map>";

	mapDoc.Parse(mapXml);

	if(mapDoc.Error())
	{
		cout << "Harita olusturma hatasi!" << endl;
	}

	height = h;
	width = w;
}

LabyrinthMap::LabyrinthMap(const char* mapXml)
{
	mapDoc.Parse(mapXml);

	if(mapDoc.Error())
	{
		cout << "Harita olusturma hatasi!" << endl;
	}
}

void LabyrinthMap::SaveMap(const char* fileName)
{
	mapDoc.SaveFile(fileName);
}

void LabyrinthMap::RealizeMap()
{
	TiXmlNode* node = 0;
	TiXmlElement* mainElement = 0;
	TiXmlElement* itemElement = 0;
	TiXmlElement* cellElement = new TiXmlElement("Cells");
	TiXmlElement* objectElement = new TiXmlElement("Objects");
	TiXmlElement* questionElement = new TiXmlElement("Questions");

	Vector3f position;
	Vector3f scale;
	Vector3f color;
	float angle;

	node = mapDoc.FirstChild("Map");
	assert(node);
	mainElement = node -> ToElement();
	assert(mainElement);

	//Odanin genel ozellikleri aliniyor
	node = mainElement->FirstChildElement("Attributes");
	itemElement = node->ToElement();
	assert(itemElement);
	this->width = atoi(itemElement->Attribute("width"));
	this->height = atoi(itemElement->Attribute("height"));
	this->name = itemElement->Attribute("name");
	//ilk oda yaratiliyor

	vector<float> walls;
	vector<vector<float>> cellVector;
	node = mainElement->FirstChildElement("Cells");
	node = node->FirstChild();
	assert(node);
	cellElement = node->ToElement();
	assert(cellElement);
	int size;
	//Cell etiketleri icinde dolasacak
	while(cellElement ->NextSiblingElement())
	{
		cellElement = node->ToElement();
		assert(cellElement);
		size = atoi(cellElement->Attribute("size"));
		node = node->FirstChild()->FirstChild();
		assert(node);
		itemElement = node->ToElement();
		assert(itemElement);

		walls.clear();
		position[0] = atof(itemElement->Attribute("coord_x"));
		walls.push_back(position[0]);
		position[2] = -atof(itemElement->Attribute("coord_y"));
		walls.push_back(position[1]);
		position[1] = atof(itemElement->Attribute("coord_z"));	
		walls.push_back(position[2]);
		scale[0] = atof(itemElement->Attribute("scale_x"));
		walls.push_back(scale[0]);
		scale[2] = atof(itemElement->Attribute("scale_y"));
		walls.push_back(scale[1]);
		scale[1] = atof(itemElement->Attribute("scale_z"));
		walls.push_back(scale[2]);
		color[0] = atof(itemElement->Attribute("red"));
		walls.push_back(color[0]);
		color[1] = atof(itemElement->Attribute("green"));
		walls.push_back(color[1]);
		color[2] = atof(itemElement->Attribute("blue"));
		walls.push_back(color[2]);
		angle = atof(itemElement->Attribute("angle"));
		walls.push_back(angle);

		cellVector.push_back(walls);

		//Wall etiketleri icinde dolasacak
		while(itemElement->NextSiblingElement())
		{
			itemElement = itemElement->NextSiblingElement();
			assert(itemElement);

			walls.clear();
			position[0] = atof(itemElement->Attribute("coord_x"));
			walls.push_back(position[0]);
			position[2] = -atof(itemElement->Attribute("coord_y"));
			walls.push_back(position[1]);
			position[1] = atof(itemElement->Attribute("coord_z"));	
			walls.push_back(position[2]);
			scale[0] = atof(itemElement->Attribute("scale_x"));
			walls.push_back(scale[0]);
			scale[2] = atof(itemElement->Attribute("scale_y"));
			walls.push_back(scale[1]);
			scale[1] = atof(itemElement->Attribute("scale_z"));
			walls.push_back(scale[2]);
			color[0] = atof(itemElement->Attribute("red"));
			walls.push_back(color[0]);
			color[1] = atof(itemElement->Attribute("green"));
			walls.push_back(color[1]);
			color[2] = atof(itemElement->Attribute("blue"));
			walls.push_back(color[2]);
			angle = atof(itemElement->Attribute("angle"));
			walls.push_back(angle);

			cellVector.push_back(walls);
		}	

		node = node->Parent()->Parent();
		assert(node);
		cellElement = node->ToElement();
		assert(cellElement);
		if(node->NextSibling())
		{
			node = node->NextSibling();
			assert(node);
		}
	}
	node = mainElement ->FirstChildElement("Objects");
	assert(node);
	objectElement = node->FirstChild()->ToElement();
	assert(objectElement);
	vector<std::string> objects;
	vector<vector<std::string>> objectVector;
	while(objectElement)
	{
		objects.clear();
		objects.push_back(objectElement->Attribute("path"));
		objects.push_back(objectElement->Attribute("texture"));
		objects.push_back(objectElement->Attribute("coord_x"));
		objects.push_back(objectElement->Attribute("coord_y"));
		objects.push_back(objectElement->Attribute("coord_z"));
		objects.push_back(objectElement->Attribute("size_x"));
		objects.push_back(objectElement->Attribute("size_y"));
		objects.push_back(objectElement->Attribute("size_z"));
		objectVector.push_back(objects);
		objectElement = objectElement ->NextSiblingElement();
	}

	node = mainElement ->FirstChildElement("Questions");
	assert(node);
	questionElement = node->FirstChild()->ToElement();
	assert(questionElement);
	vector<std::string> questions;
	vector<vector<std::string>> questionVector;
	while(questionElement)
	{
		questions.clear();
		questions.push_back(questionElement->Attribute("question"));
		questions.push_back(questionElement->Attribute("answer"));
		questionVector.push_back(questions);
		questionElement = questionElement ->NextSiblingElement();
	}

	this->questionVector = questionVector;
	this->cellVector = cellVector;
	this->objectVector = objectVector;
}

vector<vector<float>> LabyrinthMap::getCellVector()
{
	return this->cellVector;
}

vector<vector<std::string>> LabyrinthMap::getObjectVector()
{
	return this->objectVector;
}

vector<vector<std::string>> LabyrinthMap::getQuestionVector()
{
	return this->questionVector;
}

